/**********************************************************************
* Filename: CalendarDate.java
* Created: 2013/05/29
* @author Fernando Brito e Abreu
**********************************************************************/
package org.quasar.airNova.businessLayer;

import java.util.Set;
import java.util.HashSet;
import org.quasar.airNova.persistenceLayer.Database;

public class CalendarDate
{
	
	/***********************************************************
	* @return all instances of class CalendarDate
	***********************************************************/
	public static Set<CalendarDate> allInstances()
	{
		return Database.allInstances(CalendarDate.class);
	}
	
	private int day;
	private int month;
	private CalendarDate now;
	private int year;
	
	/**********************************************************************
	* Default constructor
	**********************************************************************/
	public CalendarDate()
	{
	}
	
	/**********************************************************************
	* Parameterized constructor
	* @param day the day to initialize
	* @param month the month to initialize
	* @param now the now to initialize
	* @param year the year to initialize
	**********************************************************************/
	public CalendarDate(int day, int month, int year, CalendarDate now)
	{
		this.day = day;
		this.month = month;
		this.now = now;
		this.year = year;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the day of the calendarDate
	**********************************************************************/
	public int day()
	{
		return day;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param day the day to set
	**********************************************************************/
	public void setDay(int day)
	{
		this.day = day;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the month of the calendarDate
	**********************************************************************/
	public int month()
	{
		return month;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param month the month to set
	**********************************************************************/
	public void setMonth(int month)
	{
		this.month = month;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the now of the calendarDate
	**********************************************************************/
	public CalendarDate now()
	{
		return now;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param now the now to set
	**********************************************************************/
	public void setNow(CalendarDate now)
	{
		this.now = now;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the year of the calendarDate
	**********************************************************************/
	public int year()
	{
		return year;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param year the year to set
	**********************************************************************/
	public void setYear(int year)
	{
		this.year = year;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE getter for CalendarDate[*] <-> Realizacao[*]
	* @return the realizacao of the ocorre_em
	**********************************************************************/
	public Set<Realizacao> realizacao()
	{
		Set<Realizacao> result = new HashSet<Realizacao>();
		for (Realizacao x : Realizacao.allInstances())
			if (x.ocorre_em()  ==  this)
				result.add(x);
		return result;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE setter for CalendarDate[*] <-> Realizacao[*]
	* @param realizacao the realizacao to set
	**********************************************************************/
	public void setRealizacao(Set<Realizacao> realizacao)
	{
		for (Realizacao x : realizacao)
			x.setOcorre_em(this);
	}
	
	/**********************************************************************
	* MEMBER2MEMBER getter for CalendarDate[*] <-> Voo[*]
	* @return the realiza_se of the ocorre_em
	**********************************************************************/
	public Set<Voo> realiza_se()
	{
		Set<Voo> result = new HashSet<Voo>();
		for (Realizacao x : Realizacao.allInstances())
			if (x.ocorre_em()  ==  this)
				result.add(x.realiza_se());
		return result;
	}
	
	/**********************************************************************
	* MEMBER2MEMBER setter for CalendarDate[*] <-> Voo[*]
	* @param realiza_se the realiza_se to set
	**********************************************************************/
	public void setRealiza_se(Set<Voo> realiza_se)
	{
		for (Voo t : realiza_se)
			for (Realizacao x : Realizacao.allInstances())
				if (x.ocorre_em() == this)
					x.setRealiza_se(t);
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param day the day to set
	* @param month the month to set
	* @param year the year to set
	* @param now the now to set
	**********************************************************************/
	public void init(int day, int month, int year, CalendarDate now)
	{
		//	TODO
		//	TODO;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param date the date to set
	**********************************************************************/
	public void initS(String date)
	{
		//	TODO
		//	TODO;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param t the t to set
	**********************************************************************/
	public boolean isAfter(CalendarDate t)
	{
		//	TODO
//			return if (self.year = t.year) then if (self.month = t.month) then (self.day > t.day) else (self.month > t.month) endif else (self.year > t.year) endif
		
		if(t.year() > year())
			return false;
		if(t.year() == year() && t.month() > month())
			return false;
		if(t.year() == year() && t.month() == month() && t.day() > day())
			return false;
		
		return true;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param t the t to set
	**********************************************************************/
	public boolean isBefore(CalendarDate t)
	{
		//	return if (self.year = t.year) then if (self.month = t.month) then (self.day < t.day) else (self.month < t.month) endif else (self.year < t.year) endif
		if(t.year() < year())
			return false;
		if(t.year() == year() && t.month() < month())
			return false;
		if(t.year() == year() && t.month() == month() && t.day() < day())
			return false;
		
		return true;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param x the x to set
	* @param y the y to set
	**********************************************************************/
	public boolean isDivisible(int x, int y)
	{
		//	TODO
		//	return (((x div y) * y) = x)
		return true;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param t the t to set
	**********************************************************************/
	public boolean isEqual(CalendarDate t)
	{
		return this.year == t.year && this.month == t.month && this.day == t.day;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public boolean isLeap()
	{
		//	TODO
		//	return if (self.isDivisible(self.year, 400) or self.isDivisible(self.year, 4)) then true else if self.isDivisible(self.year, 100) then false else if self.isDivisible(self.year, 4) then true else false endif endif endif
		return true;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param date the date to set
	**********************************************************************/
	public CalendarDate stringToDate(String date)
	{
		//	TODO
		//	TODO;
		return null;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	**********************************************************************/
	public CalendarDate today()
	{
		return now;
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param t the t to set
	**********************************************************************/
	public int yearsSince(CalendarDate t)
	{
		//	TODO
		//	return if ((self.month < t.month) or ((self.month = t.month) and (self.day < t.day))) then ((self.year - t.year) - 1) else (self.year - t.year) endif
		return -1;
	}
	
	/**********************************************************************
	* Object serializer
	**********************************************************************/
	public String toString()
	{
		return "CalendarDate [day=" + day + ", month=" + month + ", now=" + now + ", year=" + year + "]";
	}
	
	//	-------------------------------------------------------------------------------
	//	INVARIANTS (TODO)
	/*
	inv calendarDateUnica
		CalendarDate.allInstances->forAll(cd1 : CalendarDate, cd2 : CalendarDate | ((cd1 <> cd2) implies (((((((((cd1.day <> cd2.day) and (cd1.month <> cd2.month)) and (cd1.year <> cd2.year)) or (((cd1.day = cd2.day) and (cd1.month <> cd2.month)) and (cd1.year <> cd2.year))) or (((cd1.day <> cd2.day) and (cd1.month = cd2.month)) and (cd1.year <> cd2.year))) or (((cd1.day <> cd2.day) and (cd1.month <> cd2.month)) and (cd1.year = cd2.year))) or (((cd1.day = cd2.day) and (cd1.month <> cd2.month)) and (cd1.year = cd2.year))) or (((cd1.day = cd2.day) and (cd1.month = cd2.month)) and (cd1.year <> cd2.year))) or (((cd1.day <> cd2.day) and (cd1.month = cd2.month)) and (cd1.year = cd2.year)))))
	
	*/
}
